package common

import (
	"context"
	"go.mongodb.org/mongo-driver/bson"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"snow-im/app/utils"
	"snow-im/config"
	"sync"
	"time"
)

var MogoTool *MongoHelper

func InitMongo() {
	MogoTool = &MongoHelper{
		lock:       new(sync.Mutex),
		startCheck: false,
		url:        config.GetConf().Mongo.Url,
	}
}

type MongoHelper struct {
	lock       *sync.Mutex
	client     *mongo.Client
	startCheck bool
	password   string
	url        string
}

func (this *MongoHelper) getSession(db string) (*mongo.Client, context.Context) {
	this.lock.Lock()
	defer this.lock.Unlock()
	var err error
	if !this.startCheck {
		options := options.Client().ApplyURI(this.url)
		options.SetMaxPoolSize(1000)
		options.SetMaxConnIdleTime(4 * time.Second)
		this.client, err = mongo.NewClient(options)

		if err == nil {
			this.client.Database(db)
		} else {
			utils.Log(nil,"mongo错误", err)
		}
	}
	ctx, _ := context.WithTimeout(context.Background(), 10*time.Second)
	err = this.client.Connect(ctx)
	if err != nil {
		utils.Log(nil,"mongo错误", err)
	}
	return this.client, ctx
}

/**
*插入单条数据
 */
func (this *MongoHelper) InsertOne(db string, collection string, entity interface{}) {
	client, ctx := this.getSession(db)
	client.Database(db).Collection(collection).InsertOne(ctx, entity)
	defer client.Disconnect(ctx)
}

/**
*插入多条数据
 */
func (this *MongoHelper) InsertMany(db string, collection string, entities []interface{}) {
	client, ctx := this.getSession(db)
	client.Database(db).Collection(collection).InsertMany(ctx, entities)
	defer client.Disconnect(ctx)
}

/**
*删除数据
 */
func (this *MongoHelper) DelData(db string, collection string, filter bson.M) {
	client, ctx := this.getSession(db)
	client.Database(db).Collection(collection).DeleteMany(ctx, filter)
	defer client.Disconnect(ctx)
}

type User struct {
	Name string
	Id   int64
}

/**
*分页数据
 */
func (this *MongoHelper) PageData(db string, collection string, filter bson.M, start int64, limit int) (*mongo.Cursor, error) {
	client, ctx := this.getSession(db)
	defer client.Disconnect(ctx)
	var findoptions *options.FindOptions
	if limit > 0 {
		findoptions = &options.FindOptions{}
		findoptions.SetLimit(int64(limit))
		findoptions.SetSkip(start)
	}
	return client.Database(db).Collection(collection).Find(ctx, filter, findoptions)
}

/**
*单条数据
 */

func (this *MongoHelper) SingleData(db string, collection string, filter bson.M) (res *mongo.SingleResult) {
	client, ctx := this.getSession(db)
	defer client.Disconnect(ctx)
	return client.Database(db).Collection(collection).FindOne(ctx, filter)
}

func (this *MongoHelper) UpOrInsert(db string, collection string, filter bson.M, update bson.M) error {
	client, ctx := this.getSession(db)
	defer client.Disconnect(ctx)
	opt := options.Update().SetUpsert(true)
	_, err := client.Database(db).Collection(collection).UpdateOne(ctx, filter, update, opt)
	return err
}
func (this *MongoHelper) DeleteChild(db string, collection string, filter bson.M, update bson.M) error {
	client, ctx := this.getSession(db)
	defer client.Disconnect(ctx)
	_, err := client.Database(db).Collection(collection).UpdateOne(ctx, filter, update)
	return err
}
func (this *MongoHelper) DeleteOne(db string, collection string, filter bson.M) error {
	client, ctx := this.getSession(db)
	defer client.Disconnect(ctx)
	_, err := client.Database(db).Collection(collection).DeleteOne(ctx, filter)
	return err
}

//获取部分字段数据
func (this *MongoHelper) FieldsData(db string, collection string, filter bson.M, fields bson.M) (interface{}, error) {
	client, ctx := this.getSession(db)
	defer client.Disconnect(ctx)
	opt := options.FindOne().SetProjection(fields)
	return client.Database(db).Collection(collection).FindOne(ctx, filter, opt), nil
}
